{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Canvas Creation\n",
    "\n",
    "First, read about the [Canvas overview](Canvas-Overview.ipynb).\n",
    "\n",
    "Skia has multiple backends which receive `Canvas` drawing commands, including:\n",
    "\n",
    "- [Raster](#Raster) - CPU-only.\n",
    "- [GPU](#GPU) - Skia's GPU-accelerated backend.\n",
    "- [PDF](#PDF) - PDF document creation.\n",
    "- [Picture](#Picture) - Skia's display list format.\n",
    "- [NullCanvas](#NullCanvas) - Useful for testing only.\n",
    "- XPS - Experimental XPS backend.\n",
    "- [SVG](#SVG) - Experimental SVG backend.\n",
    "\n",
    "Each backend has a unique way of creating a Canvas. This page gives an example for each:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import skia\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from IPython.display import display, Image\n",
    "%matplotlib inline\n",
    "\n",
    "width, height = 200, 200\n",
    "\n",
    "def draw(canvas):\n",
    "    canvas.clear(skia.ColorWHITE)\n",
    "    paint = skia.Paint()\n",
    "    paint.setAntiAlias(True)\n",
    "    paint.setColor(skia.ColorGREEN)\n",
    "    canvas.drawCircle(100., 100., 40., paint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Raster\n",
    "\n",
    "The raster backend draws to a block of memory. This memory can be managed by Skia or by the client.\n",
    "\n",
    "The recommended way of creating a canvas for the Raster and Ganesh backends is to use a `Surface`, which is an object that manages the memory into which the canvas commands are drawn."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "Image(200, 200, ColorType.kRGBA_8888_ColorType, AlphaType.kPremul_AlphaType)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "surface = skia.Surface.MakeRasterN32Premul(width, height)\n",
    "canvas = surface.getCanvas()\n",
    "draw(canvas)\n",
    "image = surface.makeImageSnapshot()\n",
    "assert image is not None\n",
    "display(image)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, we could have specified the memory for the surface explicitly, instead of asking Skia to manage it. The following demonstrates using `numpy.ndarray` as a backing memory for drawing:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "array = np.zeros((height, width, 4), dtype=np.uint8)\n",
    "\n",
    "with skia.Surface(array) as canvas:\n",
    "    draw(canvas)\n",
    "\n",
    "plt.imshow(array)\n",
    "plt.show() "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## GPU\n",
    "\n",
    "GPU Surfaces must have a `GrContext` object which manages the GPU context, and related caches for textures and fonts. GrContexts are matched one to one with OpenGL contexts or Vulkan devices. That is, all `Surface` that will be rendered to using the same OpenGL context or Vulkan device should share a `GrContext`. Skia does not create a OpenGL context or Vulkan device for you. In OpenGL mode it also assumes that the correct OpenGL context has been made current to the current thread when Skia calls are made."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The following example uses `glfw` package to create an OpenGL context. Install `glfw` via pip to try."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "Image(200, 200, ColorType.kRGBA_8888_ColorType, AlphaType.kPremul_AlphaType)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import glfw\n",
    "import contextlib\n",
    "\n",
    "\n",
    "@contextlib.contextmanager\n",
    "def glfw_context():\n",
    "    if not glfw.init():\n",
    "        raise RuntimeError('glfw.init() failed')\n",
    "    glfw.window_hint(glfw.VISIBLE, glfw.FALSE)\n",
    "    glfw.window_hint(glfw.STENCIL_BITS, 8)\n",
    "    window = glfw.create_window(640, 480, '', None, None)\n",
    "    glfw.make_context_current(window)\n",
    "    yield window\n",
    "    glfw.terminate()\n",
    "\n",
    "\n",
    "with glfw_context():\n",
    "    context = skia.GrContext.MakeGL()\n",
    "    info = skia.ImageInfo.MakeN32Premul(width, height)\n",
    "    surface = skia.Surface.MakeRenderTarget(context, skia.Budgeted.kNo, info)\n",
    "    assert surface is not None\n",
    "    canvas = surface.getCanvas()\n",
    "    draw(canvas)\n",
    "    image = surface.makeImageSnapshot()\n",
    "    display(image)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## PDF\n",
    "\n",
    "The `PDF` backend uses `Document` instead of `Surface`, since a document must include multiple pages."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "path = 'output.pdf'\n",
    "\n",
    "stream = skia.FILEWStream(path)\n",
    "with skia.PDF.MakeDocument(stream) as document:\n",
    "    with document.page(width, height) as canvas:\n",
    "        draw(canvas)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Picture\n",
    "\n",
    "The `Picture` backend uses `PictureRecorder` instead of `Surface`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "recorder = skia.PictureRecorder()\n",
    "canvas = recorder.beginRecording(width, height)\n",
    "draw(canvas)\n",
    "picture = recorder.finishRecordingAsPicture()\n",
    "data = picture.serialize()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NullCanvas\n",
    "\n",
    "The null canvas is a canvas that ignores all drawing commands and does nothing."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "canvas = skia.MakeNullCanvas()\n",
    "draw(canvas)  # No op"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SVG\n",
    "\n",
    "The (still experimental) SVG canvas writes into an SVG document."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "path = 'output.svg'\n",
    "\n",
    "stream = skia.FILEWStream(path)\n",
    "canvas = skia.SVGCanvas.Make((width, height), stream)\n",
    "draw(canvas)\n",
    "del canvas  # Make sure to destroy before stream\n",
    "stream.flush()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
